//
//      CGE - CRAb Graphics Engine
// 
//      Copyright (C) 2003-2009 by CRAb-UFC
//
//		This file is part of the "CRAb Graphics Engine"
//		See the copyright notice in cge.h for conditions of distribution and use.
//

#ifndef CGE_DATAGRAMPACKET_CLASS_H__
#define CGE_DATAGRAMPACKET_CLASS_H__

#include "cgeInetAddress.h"

namespace basterd
{
	namespace net
	{ 
		/** @brief Encapsulates an UDP Datagram packet.
		 *
		 *		Datagram packets are used to implement a connectionless packet delivery service.
		 * Each message is routed from one machine to another based solely on information contained 
		 * within that packet. Multiple packets sent from one machine to another might be routed 
		 * differently, and might arrive in any order, so packet ordering may be implemented by the user.
		 *		As UDP does not provide a connection mechanism, packet delivery is not guaranteed and
		 * flow control is not provided.
		 *
		 * @see InetAddress, DatagramSocket
		 */
		class DatagramPacket
		{
			friend class DatagramSocket;

		public:

			/**
			 * Copy-constructor.
			 */
			DatagramPacket( const DatagramPacket& rhs )
				: buffer(0), length(rhs.length), address(rhs.address)
			{
				buffer = new char[rhs.length];
				memcpy( buffer, rhs.buffer, length );
			}

			/**
			 * Assignment operator. Optimized: avoids reallocation
			 */
			DatagramPacket& operator = ( const DatagramPacket& rhs )
			{
				if( length != rhs.length )
				{
					delete [] buffer;		

					length = rhs.length;
					buffer = new char[rhs.length];
				}
				
				memcpy( buffer, rhs.buffer, length );
				memcpy( &address, &rhs.address, sizeof(address));

				return *this;
			}

			/** 
			 * @brief Constructor. Builds a datagram packet and zeroises its data buffer.
			 *
			 * @remarks
			 *		Bear in mind that this constructor does not fill any address information for this datagram.
			 * Because of this, such constructor is likely to be used for receiving data from remote peers. 
			 * If you want to send data using this datagram, please set its address and port by calling setAddress()
			 * and setPort().
			 * 
			 * @param length  Length, in bytes, of the I/O buffer that will be allocated by this datagram.
			 */
			DatagramPacket( muint length );

			/** 
			 * @brief Constructor. Builds a datagram packet and zeroises its data buffer.
			 * 
			 * @param length  Length, in bytes, of the I/O buffer that will be allocated by this datagram.
			 * @param address Low-level address (IP/DNS) of the remote peer
			 * @param port    Port to send data in the remote peer.
			 */
			DatagramPacket( muint length, const sockaddr_in& address, mushort port );

			/** 
			 * @brief Constructor. Builds a datagram packet and zeroises its data buffer.
			 * 
			 * @param length  Length, in bytes, of the I/O buffer that will be allocated by this datagram.
			 * @param address Internet address (IP/DNS) of the remote peer
			 * @param port    Port to send data in the remote peer.
			 */
			DatagramPacket( muint length, const InetAddress& address, mushort port );

			/** 
			 * @brief Constructor. Builds a datagram packet and zeroizes its data buffer.
			 * 
			 * @param length  Length, in bytes, of the I/O buffer that will be allocated by this datagram.
			 * @param address String containing the IP address or DNS name of the remote peer
			 * @param port    Port to send data in the remote peer.
			 */
			DatagramPacket( muint length, const String& address, mushort port );

			/** 
			 * @brief Constructor. Builds a datagram packet and fills its data.
			 * 
			 * @param buffer  Buffer containing data to be copied to this datagram's internal buffer.
			 * @param length  Length, in bytes, of the I/O buffer that will be allocated by this datagram.
			 * @param address Internet address of the remote peer
			 * @param port    Port to send data in the remote peer.
			 */
			DatagramPacket( const char* buffer, muint length,
							const InetAddress& address, mushort port );

			/** 
			 * @brief Constructor. Builds a datagram packet and fills its data.
			 * 
			 * @param buffer  Buffer containing data to be copied to this datagram's internal buffer.
			 * @param length  Length, in bytes, of the I/O buffer that will be allocated by this datagram.
			 * @param address Low-level address of the remote peer
			 * @param port    Port to send data in the remote peer.
			 */
			DatagramPacket( const char* buffer, muint length,
							const sockaddr_in& address, mushort port );			

			/** 
			 * @brief Constructor. Builds a datagram packet and fills its data.
			 * 
			 * @param buffer  Buffer containing data to be copied to this datagram's internal buffer.
			 * @param length  Length, in bytes, of the I/O buffer that will be allocated by this datagram.
			 * @param address String containing the IP address or DNS name of the remote peer
			 * @param port    Port to send data in the remote peer.
			 */
			DatagramPacket( const char* buffer, muint length,
							const String& address, mushort port );
			
			/**
			 *  Destructor
			 */
			virtual ~DatagramPacket(void);


			/**
			 *  Sets this datagram packet as broadcast.
			 */
			void setBroadcast(mushort port);

			/**
			 * Provides access to the byte array of this packet
			 */
			      char* getBuffer(void)      { return buffer; }
		    /**
			 * Provides access to the byte array of this packet
			 */
			const char* getBuffer(void) const{ return buffer; }

			/**
			 * Provides access to the port which this packet uses to send and receive data.
			 */
			mushort getPort(void) const;

			/**
			 * Defines the port to be used by this datagram when sending data
			 *
			 * @param port Port number, ranging from 0 to 65535.
			 */
			void setPort(mushort port);

			/**
			 * Provides access to the internet address this packet uses to receive/send data.
			 */
			const sockaddr_in& getSocketAddress(void) const 
			{
				return address;
			}

			/**
			 * Provides access to the human-readable Internet address this packet uses to receive/send data.
			 */
			String getAddress(void) const;

			/**
			 * Sets the IP address, or the DNS name of the peer to send data on this datagram.
			 *
			 * @param ipAddress IP address or DNS of the remote peer.
			 */
			void setAddress(const String& ipAddress);

			/**
			 * Gets the InetAddress structure for this packet's address.
			 */
			void getAddress(InetAddress& inetaddr) const
			{
				inetaddr = address;
			}

			/** Index operator (read-write version)
			 */
			mubyte& operator []( muint i)
			{
				return ((mubyte*)buffer)[i];
			}

			/** Index operator (read-only version)
			 */
			const mubyte& operator [] ( muint i) const
			{
				return ((mubyte*)buffer)[i];
			}

		protected:

			/**
			 * Buffer used for sending/receiving data.
			 */			 
			char* buffer;

			/**
			 * Length of the buffer, in bytes. 
			 */
			muint   length;

			/**
			 * Internet address used by this datagram. 
			 */
			sockaddr_in address;

		}; // end of the DatagramPacket class
		
		/// For ease of coding, defines an UdpPacket type
		typedef DatagramPacket UdpPacket;
	}
}



#endif // CGE_SERVER_CLASS_H__
